P4-ReplicaSet Controller
前言
在上一篇文章中,对deployment controller的工作模式进行了详细地分析:
分析后得知,deployment controller更多的是对每个相应版本的replicaset副本数进行管理,而不涉及直接对pod的管理,因此,承接上节,本章来分析replicaSet Controller的源码.
ReplicaSet Controller
初始化
参照上节一样,直接来到各类controller初始化的函数:
cmd/kube-controller-manager/app/controllermanager.go:343
1 | controllers["replicaset"] = startReplicaSetController |
==> cmd/kube-controller-manager/app/apps.go:69
1 | go replicaset.NewReplicaSetController( |
创建ReplicaSetController
先来看看NewReplicaSetController创建的过程:
==> pkg/controller/replicaset/replica_set.go:109
1 | func NewReplicaSetController(rsInformer appsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, kubeClient clientset.Interface, burstReplicas int) *ReplicaSetController { |
NewBaseController这里主要关注AddEventHandler为资源的informer增加的curd方法,例如pod相关的addPod、updatePod、deletePod方法。
ReplicaSetController Run方法
接着往下,创建好ReplicaSetController对象后,看它的运行过程,即Run方法。
==> pkg/controller/replicaset/replica_set.go:177
1 | // Run begins watching and syncing. |
来到了这里,可发现ReplicaSetController.Run()函数和上一节的DeploymentController.Run()函数非常地相似。所以,从这里开始,各类controller之间代码相似的步骤可能会跳过,不再每个地方都重复详细说明。
往上溯源,可以找到,worker的数量配置默认为5个,参见这里:
pkg/controller/apis/config/v1alpha1/defaults.go:219
1 | func SetDefaults_ReplicaSetControllerConfiguration(obj *kubectrlmgrconfigv1alpha1.ReplicaSetControllerConfiguration) { |
wait.Until()函数是很有意思的,上节也做过仔细分析,可以再回顾一下这里:
好,直接进入主题,开始分析rsc.worker工作函数.
工作逻辑
pkg/controller/replicaset/replica_set.go:190
1 | for i := 0; i < workers; i++ { |
==> pkg/controller/replicaset/replica_set.go:432
1 | // processNextWorkItem()函数的作用是把informer work queue工作队列里的对象取出,按照申明的要求来处理它们,标记它们。 |
==> pkg/controller/replicaset/replica_set.go:437
1 | func (rsc *ReplicaSetController) processNextWorkItem() bool { |
主要函数是这个syncHandler,接着追溯,可以在这里找到这个结构体属性函数的赋值:
pkg/controller/replicaset/replica_set.go:163
1 | // NewBaseController is the implementation of NewReplicaSetController with additional injected |
接着便可以找到ReplicaSetController.syncReplicaSet函数:
pkg/controller/replicaset/replica_set.go:562
1 |
|
划重点,两个重要的函数:SatisfiedExpectations(判断是否满足sync条件) / manageReplicas(sync后续的副本pod新增、删除操作)。分别来看看
SatisfiedExpectations函数
在此之前,必须先了解一下rs controller(后面简称rsc)的Expectations机制。rsc会将每一个rs的期望状态(比如期望新增3个副本)保存在本地缓存中,在sync执行之前,会对期望状态进行条件判断,满足条件才会真正进行sync操作。
来看看SatisfiedExpectations函数的逻辑:
pkg/controller/controller_utils.go:181
1 | func (r *ControllerExpectations) SatisfiedExpectations(controllerKey string) bool { |
manageReplicas函数
==> pkg/controller/replicaset/replica_set.go:459
1 | func (rsc *ReplicaSetController) manageReplicas(filteredPods []*v1.Pod, rs *apps.ReplicaSet) error { |
这个函数即是实际操控管理pod副本数量的函数,其中的slowStartBatch批量启动pod的功能比较有意思,来看看。
批量启动pod
pkg/controller/replicaset/replica_set.go:658
1 | func slowStartBatch(count int, initialBatchSize int, fn func() error) (int, error) { |
ReplicaSetController工作流程总结
总结一下,在出现新版本的rs后,rsc按照以下步骤进行工作:
1.通过SatisfiedExpectations函数,发现expectations期望状态本地缓存中不存在此rs key,因此返回true,需要sync
2.通过manageReplicas管理pod,新增或删除
3.判断pod副本数是多了还是少了,多则要删,少则要增
4.增删之前创建expectations对象并设置add / del值
5.slowStartBatch新增 / 并发删除 pod
6.更新expection
expections缓存机制,在运行的pod副本数在向声明指定的副本数收敛之时,很好地避免了频繁的informer数据查询,以及可能随之而来的数据更新不及时的问题,这个机制设计巧妙贯穿整个rsc工作过程,也是不太易于理解之处。